#include <am.h>
#include <nemu.h>

#define AUDIO_FREQ_ADDR      (AUDIO_ADDR + 0x00)
#define AUDIO_CHANNELS_ADDR  (AUDIO_ADDR + 0x04)
#define AUDIO_SAMPLES_ADDR   (AUDIO_ADDR + 0x08)
#define AUDIO_SBUF_SIZE_ADDR (AUDIO_ADDR + 0x0c)
#define AUDIO_INIT_ADDR      (AUDIO_ADDR + 0x10)
#define AUDIO_COUNT_ADDR     (AUDIO_ADDR + 0x14)

static volatile int count = 0;

void __am_audio_init() {
	outl(AUDIO_INIT_ADDR,0);
}

void __am_audio_config(AM_AUDIO_CONFIG_T *cfg) {
  cfg->present = true;
 // cfg->bufsize = ; 
}

void __am_audio_ctrl(AM_AUDIO_CTRL_T *ctrl) {
  outl(AUDIO_FREQ_ADDR,ctrl->freq);
  outl(AUDIO_CHANNELS_ADDR,ctrl->channels);
  outl(AUDIO_SAMPLES_ADDR,ctrl->samples);
  outl(AUDIO_COUNT_ADDR,count);
}

void __am_audio_status(AM_AUDIO_STATUS_T *stat) {
  stat->count=inl(AUDIO_COUNT_ADDR);
}

 

void __am_audio_play(AM_AUDIO_PLAY_T *ctl) {

 uint8_t *sbuf = (uint8_t *)(uintptr_t)AUDIO_SBUF_ADDR;
 uint8_t *guestsbuf = (uint8_t *)(uintptr_t)ctl->buf.start; 
 int len = ctl->buf.end - ctl->buf.start;
 count = inl(AUDIO_COUNT_ADDR);
 int write = 0;
 outl(AUDIO_INIT_ADDR,1);
   while(!write){
   count = inl(AUDIO_COUNT_ADDR);
   if(count < 65536-len)
   {  
     for (int i = 0; i < len; i++){
       sbuf[i+count] = guestsbuf[i];
     }
    write = 1;
    count += len;
    outl(AUDIO_INIT_ADDR,0);
   }
 }
 outl(AUDIO_COUNT_ADDR,count);
// putch('w');
// putch('\n');
}
